# @Time : 2021/10/13 11:58
# @Author : Fioman 
# @Phone : 13149920693
"""
3拼板的代码逻辑
"""
import imutils

import os
import cv2 as cv
import numpy as np
import time
from vision_process.image_deal import jointLinePos, jointLineExtend, get_angle_by_k, get_rect_points_clockwise, distance
from vision_process.image_operation import *
from tools.fioman_math_tools import *
from tools.config_params import ConfigParams

cp = ConfigParams()

calcArgs = {
    "1": [[2], 10, 11, 8, 15, [60, 40, 100, 120, 150], 0.2],
    "2": [[15, 120], 10, 11, 8, 20, [80, 40, 20], 0.4],
    "3": [[5], 17, 11, 8, 20, [100, 80, 60, 50], 0.5],
    "4": [[2], 17, 17, 8, 20, [40, 30, 20, 10], 0.2],
}
tryBeginIndex = 1
minLineLength = int(30 * cp.mm2pix)  # 线条最短是多少,50个mm
lineLengthMin = int(30 * cp.mm2pix)
maxLineGap = 5
upBoxSlice = 0.4633
middleBoxSlice = (0.3, 0.73)
downBoxSlice = 0.54

# 颜色元组
colorBlue = (255, 0, 0)
colorGreen = (0, 255, 0)
colorRed = (0, 0, 255)


def image_show(name, image, showState=False):
    """
    显示图片
    :param name:
    :param image:
    :param showState:
    :return:
    """
    if showState:
        if name == "resultImage":
            scaleRate = 2
        else:
              scaleRate = 4
        width = int(image.shape[1] / scaleRate)
        height = int(image.shape[0] / scaleRate)
        showImg = cv.resize(image, (width, height), cv.INTER_AREA)
        cv.namedWindow("{}".format(name))
        cv.imshow("{}".format(name), showImg)
        cv.waitKey(0)


def get_width_height(fileName):
    """
    根据图像后去文件名的宽和高
    :param fileName:
    :return:
    """
    if "w_" not in fileName or "h_" not in fileName:
        return None, None
    wIndex = fileName.index("w_")
    hIndex = fileName.index("h_")
    width = int(fileName[wIndex + 2:wIndex + 6])
    height = int(fileName[hIndex + 2: hIndex + 6])
    return width, height


def check_total_board_is_ok_for_three(image):
    tablePos = int(np.mean(image[300:361, 1010:1461]))
    sensorPos = int(np.mean(image[362:440, 1010:1461]))
    imageGray, totalBoardBox, totalBoardThres = find_total_board(image)
    (cx, cy), (w, h), angle = totalBoardBox
    widthChecked, heightChecked = w / cp.mm2pix, h / cp.mm2pix

    if sensorPos < 20 or tablePos > 20:
        return False, "传感器Pix = {},台布Pix = {},高度 = {:.2f},宽度 = {:.2f}".format(sensorPos, tablePos, heightChecked,
                                                                              widthChecked), imageGray, totalBoardBox, totalBoardThres
    else:
        return True, "传感器Pix = {},台布Pix = {},高度 = {:.2f},宽度 = {:.2f}".format(sensorPos, tablePos, heightChecked,
                                                                             widthChecked), imageGray, totalBoardBox, totalBoardThres


def get_inner_board_info_for_size_check(board, jointLine1, jointLine2, width, height, ):
    boardColor = cv.cvtColor(board.copy(), cv.COLOR_GRAY2BGR)
    sizeOkRes = []
    for tryTimes in range(tryBeginIndex, len(calcArgs.keys()) + 1):
        cv.destroyAllWindows()
        gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate = calcArgs.get(str(tryTimes))
        print("进行第{}次计算,计算参数:(高斯半径:{}),(方差核大小:{}),(膨胀腐蚀核:{}),(膨胀腐蚀次数:{}),(腐蚀膨胀次数:{}),(阈值offset:{}),(scharr比例:{})".format(
            tryTimes, gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate))
        if len(gaussianR) == 1:
            if gaussianR[0] == 0:
                blurred = board.copy()
            else:
                blurred = cv.GaussianBlur(board, (0, 0), gaussianR[0])
        else:
            d, colorSigma = gaussianR
            spaceSigma = int(d / 2)
            blurred = cv.bilateralFilter(board, d, colorSigma, spaceSigma)

        if scharrRate == 0:
            scharrXY = blurred.copy()
        else:
            scharrX = cv.Scharr(blurred, cv.CV_64F, 1, 0)
            scharrY = cv.Scharr(blurred, cv.CV_64F, 0, 1)
            scharrX = cv.convertScaleAbs(scharrX)
            scharrY = cv.convertScaleAbs(scharrY)
            scharrXY = cv.addWeighted(scharrX, scharrRate, scharrY, scharrRate, 0)
            scharrXY = cv.bitwise_and(scharrXY, jointLine1)
        image_show("ScharrXY", scharrXY)

        img32 = np.float32(scharrXY)
        square1 = cv.blur(np.multiply(img32, img32), (squareR, squareR))
        square2 = np.multiply(cv.blur(img32, (squareR, squareR)), cv.blur(img32, (squareR, squareR)))
        squareDif32 = np.subtract(square1, square2)
        squareDif = squareDif32.copy()
        np.clip(squareDif32, 0, 255, out=squareDif)
        squareDif = squareDif.astype(np.uint8)
        image_show("SquareDif", squareDif)

        # 1. 进行膨胀腐蚀,分割图像
        contourImg = squareDif.copy()
        kernelUsed = cv.getStructuringElement(cv.MORPH_RECT, (dilateKernel, dilateKernel))
        contourImg = cv.dilate(contourImg, kernelUsed, iterations=dilateTimes)
        contourImg = cv.erode(contourImg, kernelUsed, iterations=dilateTimes)

        squareDifErode = contourImg.copy()
        for index, thresOffset in enumerate(thresOffsetList):
            cv.destroyAllWindows()
            image_show("squareDifDilateErode", squareDifErode)
            centerX, centerY = int(squareDifErode.shape[1] / 2), int(squareDifErode.shape[0] / 3)
            yChoosePos = int(0.15 * squareDifErode.shape[0])
            xChoosePos = int(0.15 * squareDifErode.shape[1])
            thresUsedImg = squareDifErode[centerY - yChoosePos:centerY + yChoosePos, centerX - xChoosePos:centerX + xChoosePos]
            image_show("ThresUsedImage", thresUsedImg)
            imageUsedMean = float(np.mean(thresUsedImg))
            thresUsedVal = int(imageUsedMean + thresOffset)
            if thresUsedVal >= 210:
                thresUsedVal = 210
            print("第 {} 个阈值,使用阈值 = {:.2f},mean(imageUsed) = {:.2f},thresOffset = {}".format(
                index + 1, thresUsedVal, imageUsedMean, thresOffset))
            _, contourImg = cv.threshold(squareDifErode, thresUsedVal, 255, cv.THRESH_BINARY)

            # 处理拼接处,当scharrRate = 0的时候
            if scharrRate == 0:
                contourImg = cv.subtract(contourImg, jointLine2)

            # 进行泛红填充
            mask = np.zeros((contourImg.shape[0] + 2, contourImg.shape[1] + 2), dtype=np.uint8)
            floodFillStartPos = (contourImg.shape[1] // 2, contourImg.shape[0] // 2)
            if contourImg[floodFillStartPos[1], floodFillStartPos[0]] > 100:
                floodFillStartPos = (contourImg.shape[1] // 3, contourImg.shape[0] // 3)
            cv.floodFill(contourImg, mask, floodFillStartPos, 150)
            floodFill = np.zeros(contourImg.shape, dtype=np.uint8)
            floodFill[contourImg == 150] = 250
            image_show("FloodFill", floodFill)

            # 进行腐蚀膨胀,去除掉边界的噪点
            floodFill = cv.erode(floodFill, kernelUsed, iterations=erodeTimes)
            floodFill = cv.dilate(floodFill, kernelUsed, iterations=erodeTimes)
            image_show("FloodFillErodeDilate", floodFill)

            if tryTimes == 2 or tryTimes == 3:
                chooseCloseInner = True  # 选择推测的线条的位置,如果是用的最后一个高斯滤波,内板上基本上就米有直线了,所以这个时候可以
                # 激进一点,使用靠近内板的那个值,来当作物料的边界地方
            else:
                chooseCloseInner = False
            res = check_inner_board_for_size_check_3(floodFill, width, height, boardColor, chooseCloseInner)
            calcSizePix = (int(res["calcSize"][0] * cp.mm2pix), int(res["calcSize"][1] * cp.mm2pix))
            print("计算结果: {},info: {},尺寸: {},{},误差: {}".format(
                res["result"], res["info"], res["calcSize"], calcSizePix, res["calcError"]))

            if res["result"] != "error":
                sizeOkRes.append(res)
                continue
    else:
        sizeList = []
        boxList = []
        if len(sizeOkRes) >= 1:
            resOkSorted = sorted(sizeOkRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            for res in resOkSorted:
                sizeList.append(res["calcSize"])
                boxList.append(res["box"])
            return "ok", sizeList, boxList
        else:
            return "error", [], []


def check_inner_board_for_size_check_3(board, width, height, boardColor, chooseCloseInner=False):
    """
    尺寸确认的时候检测找到的内板的尺寸是否正确
    :param board:
    :param width:
    :param height:
    :param bardColor:
    :param chooseCloseInner:
    :return:
    """
    global minLineLength, maxLineGap, lineLengthMin
    useImage = boardColor.copy()
    boardArea = width * height
    totalHeightPix, totalWidthPix = board.shape[:2]
    totalWidthMm, totalHeightMm = round(totalWidthPix / cp.mm2pix, 2), round(totalHeightPix / cp.mm2pix, 2)
    moveWidth13 = int(totalWidthPix * 0.21)
    moveWidthMid = int(totalWidthPix * 0.34)
    moveHeight = int(totalHeightPix * 0.3)
    res = {
        "result": "error",
        "box": None,
        "info": "",
        "calcSize": (totalWidthMm, totalHeightMm),
        "calcError": (0, 0)
    }
    moveAngleUsed = board.copy()

    try:
        # 1. 先去掉四个角,注意中缝那里去除的角多一点,因为中缝那里的特征有时候会有不明显的地方
        cv.rectangle(moveAngleUsed, (0, 0), (moveWidth13, moveHeight), 0, -1)
        cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1], 0), (moveAngleUsed.shape[1] - moveWidth13, moveHeight), 0, -1)
        cv.rectangle(moveAngleUsed, (0, moveAngleUsed.shape[0] - moveHeight), (moveWidthMid, moveAngleUsed.shape[0]), 0, -1)
        cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1] - moveWidthMid, moveAngleUsed.shape[0] - moveHeight),
                     (moveAngleUsed.shape[1], moveAngleUsed.shape[0]), 0, -1)

        image_show("MoveAngle", moveAngleUsed)
        cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
        if len(cnts) == 0:
            res["result"] = "error"
            res["info"] = "上框 找内板失败,没有找到任何的轮廓"
            res["calcSize"] = (totalWidthMm, totalHeightMm)
            res["calcError"] = (round(totalWidthMm - width / cp.mm2pix, 2), round(totalHeightMm - height / cp.mm2pix))
            return res

        cntFindAgain = False  # 是否需要再找一遍轮廓
        _, (w, h), _ = cv.minAreaRect(cntsSorted[0])
        rectBox = cv.minAreaRect(cntsSorted[0])
        rectBoxPoints = np.int0(cv.boxPoints(rectBox))
        leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
        cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
        image_show("InnerBoardFinded", useImage)
        res["box"] = [leftTop, rightTop, rightBottom, leftBottom]
        widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
        heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
        res["calcSize"] = (widthFinded, heightFinded)
        res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
        areaFinded = w * h
        if areaFinded < 0.8 * boardArea:
            res["result"] = "error"
            res["info"] = "上框 找内板失败,找到的内板面积过小"
            return res
        elif boardArea > 1.5 * boardArea:
            res["result"] = "error"
            res["info"] = "上框 找内板失败,找到的内板的面积过大"
        else:
            # 获取到物料边缘的距离
            line1 = [leftTop, rightTop]
            line2 = [rightTop, rightBottom]
            line3 = [rightBottom, leftBottom]
            line4 = [leftBottom, leftTop]

            line5 = [(0, 0), (totalWidthPix, 0)]
            line6 = [(totalWidthPix, 0), (totalWidthPix, totalHeightPix)]
            line7 = [(totalWidthPix, totalHeightPix), (0, totalHeightPix)]
            line8 = [(0, totalHeightPix), (0, 0)]

            offset1 = get_two_line_distance(line1, line5) / cp.mm2pix
            offset2 = get_two_line_distance(line2, line6) / cp.mm2pix
            offset3 = get_two_line_distance(line3, line7) / cp.mm2pix
            offset4 = get_two_line_distance(line4, line8) / cp.mm2pix

            print("offsetMm: {:.2f}, {:.2f}, {:.2f}, {:.2f}, offsetPix: {},{},{},{}".format(
                offset1, offset2, offset3, offset4, int(offset1 * cp.mm2pix), int(offset2 * cp.mm2pix),
                int(offset3 * cp.mm2pix), int(offset4 * cp.mm2pix)))

            offset1Limit = 10
            offset3Limit = 10

            # 推测第一边
            if offset1 < offset1Limit and offset3 > offset3Limit:
                findLineBoard = board.copy()[:int(board.shape[0] * 0.4)]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeTop", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        lineLength = distance((x1, y1,), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle > 45):
                            continue
                        yMin = 10 * cp.mm2pix
                        yMax = board.shape[0] - height - 10 * cp.mm2pix
                        if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and \
                                yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)

                if len(linesList) >= 2:
                    image_show("EdgeFindedTop", board1)
                    cntFindAgain = True
                    linesListFinal = sorted(linesList, key=lambda x: x[1])
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    slicePos = int(min(y1, y2))  # 按照最小的那个去截取
                    moveAngleUsed[:slicePos, :] = 0
                    image_show("moveAngleAfterSliceTop", moveAngleUsed)

            # 如果第一边位置是对的,推测第三边
            if offset1 > offset1Limit and offset3 < offset3Limit:
                yOffset = int(board.shape[0] * 0.5)
                findLineBoard = board.copy()[yOffset:]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeBottom", findLineBoard)

                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        y1 += yOffset
                        y2 += yOffset
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) > 45:
                            continue

                        yMin = board1.shape[0] * 0.5
                        yMax = board1.shape[0] - 15 * cp.mm2pix

                        if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and \
                                yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)

                if len(linesList) >= 2:
                    image_show("EdgeFindedBottom", board1)
                    cntFindAgain = True
                    linesListFinal = sorted(linesList, key=lambda x: x[1])
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    slicePos = int(max(y1, y2))  # 按最大的那个去截取
                    moveAngleUsed[slicePos:, :] = 0
                    image_show("moveAngleAfterSliceBottom", moveAngleUsed)

            # 如果第二边是对的,第四边是错误的,就证明第四边需要重新加载.
            if offset2 > 10 and offset4 < 10:
                findLineBoard = board.copy()[:, :int(board.shape[1] * 0.4)]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeLeft", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) < 45:
                            continue

                        xMin = 8 * cp.mm2pix
                        xMax = board1.shape[1] / 4
                        if abs(x2 - x1) < 10 * cp.mm2pix and abs(y2 - y1) > 5 * cp.mm2pix and xMin < x1 < xMax and \
                                xMin < x2 < xMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
                if len(linesList) >= 2:
                    image_show("EdgeFindedLeft", board1)
                    cntFindAgain = True
                    if chooseCloseInner:
                        linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[0])
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    x1 = targetLine[0][0]
                    x2 = targetLine[1][0]
                    slicePos = int(min(x1, x2))
                    moveAngleUsed[:, :slicePos] = 0
                    image_show("moveAngleAfterSliceLeft", moveAngleUsed)

            if offset2 < 10 and offset4 > 10:
                xOffset = int(board.shape[1] * 0.7)
                findLineBoard = board.copy()[:, xOffset:]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeLeft", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        x1 += xOffset
                        x2 += xOffset
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) < 45:
                            continue

                        xMin = board1.shape[1] * 0.7
                        xMax = board1.shape[1] - 10 * cp.mm2pix
                        if abs(x2 - x1) < 10 * cp.mm2pix and abs(y2 - y1) > 5 * cp.mm2pix and xMin < x1 < xMax and \
                                xMin < x2 < xMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
                if len(linesList) >= 2:
                    image_show("EdgeFindedLeft", board1)
                    cntFindAgain = True
                    if chooseCloseInner:
                        linesListFinal = sorted(linesList, key=lambda x: x[0])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    x1 = targetLine[0][0]
                    x2 = targetLine[1][0]
                    slicePos = int(max(x1, x2))
                    moveAngleUsed[:, slicePos:] = 0
                    image_show("moveAngleAfterSliceLeft", moveAngleUsed)

            if cntFindAgain:
                cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
                cnts = imutils.grab_contours(cnts)
                cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
                rectBox = cv.minAreaRect(cntsSorted[0])
                rectBoxPoints = np.int0(cv.boxPoints(rectBox))
                useImage = boardColor.copy()
                cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
                image_show("InnerBoardFindedByFillEdgeZero", useImage)
                leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
                res["box"] = leftTop, rightTop, rightBottom, leftBottom
                widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)

                # 再计算一次是否有错误的信息
                line1 = [leftTop, rightTop]
                line2 = [rightTop, rightBottom]
                line3 = [rightBottom, leftBottom]
                line4 = [leftTop, leftBottom]

                offset1 = get_two_line_distance(line1, line5) / cp.mm2pix
                offset2 = get_two_line_distance(line2, line6) / cp.mm2pix
                offset3 = get_two_line_distance(line3, line7) / cp.mm2pix
                offset4 = get_two_line_distance(line4, line8) / cp.mm2pix

            topLineAngle = get_angle_by_k(get_line_k(leftTop, rightTop))
            if abs(topLineAngle) > 18:
                res["result"] = "error"
                res["info"] = "识别的内框的第一边的角度太大,角度为: {:.2f}".format(topLineAngle)
                res["calcSize"] = (widthFinded, heightFinded)
                res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                return res

            if min(offset1, offset2, offset3, offset4) < 8:
                res["result"] = "error"
                res["info"] = "识别的内框太靠近物料边缘,{:.2f},{:.2f},{:.2f},{:.2f}".format(offset1, offset2, offset3, offset4)
                res["calcSize"] = (widthFinded, heightFinded)
                res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                return res
            else:
                res["result"] = "ok"
                res["info"] = "识别成功!"
                res["calcSize"] = (widthFinded, heightFinded)
                res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                return res

    except Exception as e:
        errorInfo = "in check_inner_board_for_size_check() error: {}".format(str(e))
        print(errorInfo)
        res["result"] = "error"
        res["info"] = errorInfo
        res["calcSize"] = (totalWidthMm, totalHeightMm)
        res["calcError"] = (round(totalWidthMm - width / cp.mm2pix, 2), round(totalHeightMm - height / cp.mm2pix, 2))
        return res


def get_inner_board_info_3(board, jointLine1, jointLine2, width, height, calcThresBig, calcThresSmall, boardPos, nearBox=None,
                           totalBoardHeight=None):
    """
    3拼板获取内板信息
    :param board:
    :param jointLine1:
    :param jointLine2:
    :param width:
    :param height:
    :param calcThresBig:
    :param calcThresSmall:
    :param boardPos:
    :param nearBox:
    :param totalBoardHeight
    :return:
    """
    res = {
        "result": "error",
        "info": "识别错误",
        "box": None
    }
    boardColor = cv.cvtColor(board.copy(), cv.COLOR_GRAY2BGR)
    sizeOkRes = []
    sizeDifRes = []
    sizeOkByExtendRes = []
    for tryTimes in range(tryBeginIndex, len(calcArgs.keys()) + 1):
        cv.destroyAllWindows()
        gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate = calcArgs.get(str(tryTimes))
        print("进行第{}次计算,计算参数:(高斯半径:{}),(方差核大小:{}),(膨胀腐蚀核:{}),(膨胀腐蚀次数:{}),(腐蚀膨胀次数:{}),(阈值offset:{}),(scharr比例:{})".format(
            tryTimes, gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate))

        if len(gaussianR) == 1:
            if gaussianR[0] == 0:
                blurred = board.copy()
            else:
                blurred = cv.GaussianBlur(board, (0, 0), gaussianR[0])
        else:
            d, colorSigma = gaussianR
            spaceSigma = int(d / 2)
            blurred = cv.bilateralFilter(board, d, colorSigma, spaceSigma)

        if scharrRate == 0:
            scharrXY = blurred.copy()
        else:
            scharrX = cv.Scharr(blurred, cv.CV_64F, 1, 0)
            scharrY = cv.Scharr(blurred, cv.CV_64F, 0, 1)
            scharrX = cv.convertScaleAbs(scharrX)
            scharrY = cv.convertScaleAbs(scharrY)
            scharrXY = cv.addWeighted(scharrX, scharrRate, scharrY, scharrRate, 0)
            scharrXY = cv.bitwise_and(scharrXY, jointLine1)
        image_show("ScharrXY", scharrXY)

        img32 = np.float32(scharrXY)
        square1 = cv.blur(np.multiply(img32, img32), (squareR, squareR))
        square2 = np.multiply(cv.blur(img32, (squareR, squareR)), cv.blur(img32, (squareR, squareR)))
        squareDif32 = np.subtract(square1, square2)
        squareDif = squareDif32.copy()
        np.clip(squareDif32, 0, 255, out=squareDif)
        squareDif = squareDif.astype("uint8")
        image_show("SquareDif", squareDif)

        # 1.进行膨胀腐蚀,分割图像
        contourImg = squareDif.copy()
        kernelUsed = cv.getStructuringElement(cv.MORPH_RECT, (dilateKernel, dilateKernel))
        contourImg = cv.dilate(contourImg, kernelUsed, iterations=dilateTimes)
        contourImg = cv.erode(contourImg, kernelUsed, iterations=dilateTimes)

        squareDifErode = contourImg.copy()
        for index, thresOffset in enumerate(thresOffsetList):
            cv.destroyAllWindows()
            image_show("squareDifDilateErode", squareDifErode)
            centerX, centerY = int(squareDifErode.shape[1] / 2), int(squareDifErode.shape[0] / 3)
            yChoosePos = int(0.15 * squareDifErode.shape[0])
            xChoosePos = int(0.15 * squareDifErode.shape[1])
            thresUsedImg = squareDifErode[centerY - yChoosePos:centerY + yChoosePos, centerX - xChoosePos:centerX + xChoosePos]
            image_show("ThresUsedImage", thresUsedImg)
            imageUsedMean = float(np.mean(thresUsedImg))
            thresUsedVal = imageUsedMean + thresOffset
            if thresUsedVal >= 220:
                thresUsedVal = 220
            print("第 {} 个阈值,使用阈值 = {:.2f}, mean(imageUsed) = {:.2f},thresOffset = {}".format(index + 1, thresUsedVal,
                                                                                             imageUsedMean, thresOffset))
            _, contourImg = cv.threshold(squareDifErode, thresUsedVal, 255, cv.THRESH_BINARY)

            # 处理拼接处,当scharrRate = 0的时候
            if scharrRate == 0:
                contourImg = cv.subtract(contourImg, jointLine2)

            # 进行泛红填充
            mask = np.zeros((contourImg.shape[0] + 2, contourImg.shape[1] + 2), dtype=np.uint8)
            floodFillStartPos = (contourImg.shape[1] // 2, contourImg.shape[0] // 2)
            if contourImg[floodFillStartPos[1], floodFillStartPos[0]] > 100:
                floodFillStartPos = (contourImg.shape[1] // 3, contourImg.shape[0] // 3)
            cv.floodFill(contourImg, mask, floodFillStartPos, 150)
            floodFill = np.zeros(contourImg.shape, dtype=np.uint8)
            floodFill[contourImg == 150] = 250
            image_show("FloodFill", floodFill)

            # 然后是进行腐蚀膨胀,去除掉边界的噪点
            floodFill = cv.erode(floodFill, kernelUsed, iterations=erodeTimes)
            floodFill = cv.dilate(floodFill, kernelUsed, iterations=erodeTimes)
            image_show("FloodFillErodeDilate", floodFill)

            if tryTimes == 2 or tryTimes == 3:
                chooseCloseInner = True  # 选择推测的线条的位置,如果是用的最后一个高斯滤波,内板上基本上就米有直线了,所以这个时候可以
                # 激进一点,使用靠近内板的那个值,来当作物料的边界地方
            else:
                chooseCloseInner = False
            res = check_inner_board_size(floodFill, width, height, calcThresBig, calcThresSmall, boardPos,
                                         boardColor, nearBox, chooseCloseInner, totalBoardHeight)
            print("计算结果: {},info:{},尺寸:{},{},误差:{}".format(
                res["result"], res["info"], res["calcSize"],
                (int(res["calcSize"][0] * cp.mm2pix), int(res["calcSize"][1] * cp.mm2pix)),
                res["calcError"]))

            if res["result"] == "big":
                sizeDifRes.append(res)
                if erodeTimes < 20:
                    erodeTimes += 2
                continue
            elif res["result"] == "small":
                sizeDifRes.append(res)
                if erodeTimes > 8:
                    erodeTimes -= 2
                continue
            elif res["result"] == "okByExtend":
                sizeOkByExtendRes.append(res)
                continue
            elif res["result"] == "ok":
                sizeOkRes.append(res)
                if int(np.sum([abs(res["calcError"][0]), abs(res["calcError"][1])])) < 7:  # 如果不是做首片,并且阈值小于8个mm,就直接返回.
                    print("返回的ok结果是,尺寸:{},{},误差:{}".format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                                             int(res["calcSize"][1] * cp.mm2pix)),
                                                           res["calcError"]))
                    return "ok", res["info"], res["box"]
                continue
    else:
        if len(sizeOkRes) >= 1:
            resOkSorted = sorted(sizeOkRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            res = resOkSorted[0]
            print("返回的ok结果是,尺寸:{},{},误差:{}".format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                                     int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
            return "ok", res["info"], res["box"]
        if len(sizeOkByExtendRes) >= 1:
            resOkSorted = sorted(sizeOkByExtendRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            res = resOkSorted[0]
            print("返回的通过推测的ok结果,尺寸:{},{},误差:{}".format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                                         int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
            return "ok", res["info"], res["box"]
        if len(sizeDifRes) >= 1:
            resSorted = sorted(sizeDifRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            res = resSorted[0]
            return "sizeDif", res["info"], res["box"]
        else:
            return "error", res["info"], res["box"]


def check_inner_board_size(board, width, height, calcThresBig, calcThresSmall, boardPos, boardColor, nearBox,
                           chooseCloseInner, totalBoardHeight):
    """
    验证找到的内板的尺寸是否正确
    :param board:
    :param width:
    :param height:
    :param calcThresBig:
    :param calcThresSmall:
    :param boardPos:
    :param boardColor:
    :param nearBox:
    :param chooseCloseInner:
    :param totalBoardHeight:
    :return:
    """
    global minLineLength, maxLineGap, lineLengthMin
    useImage = boardColor.copy()
    boardArea = width * height
    totalHeightPix, totalWidthPix = board.shape[:2]
    totalWidthMm, totalHeightMm = round(totalWidthPix / cp.mm2pix, 2), round(totalHeightPix / cp.mm2pix, 2)
    moveWidth13 = int(totalWidthPix * 0.21)
    moveWidthMid = int(totalWidthPix * 0.34)
    moveHeight = int(totalHeightPix * 0.3)

    res = {
        "result": "error",
        "box": None,
        "info": "",
        "calcSize": (totalWidthMm, totalHeightMm),
        "calcError": (0, 0)
    }

    widthMax = width / cp.mm2pix + calcThresBig
    widthMin = width / cp.mm2pix - calcThresSmall
    heightMax = height / cp.mm2pix + calcThresBig
    heightMin = height / cp.mm2pix - calcThresSmall

    moveAngleUsed = board.copy()

    try:
        if boardPos == "up":
            cv.rectangle(moveAngleUsed, (0, 0), (moveWidth13, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1], 0), (moveAngleUsed.shape[1] - moveWidth13, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, moveAngleUsed.shape[0] - moveHeight), (moveWidthMid, moveAngleUsed.shape[0]), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1] - moveWidthMid, moveAngleUsed.shape[0] - moveHeight),
                         (moveAngleUsed.shape[1], moveAngleUsed.shape[0]), 0, -1)
        else:
            cv.rectangle(moveAngleUsed, (0, 0), (moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1], 0), (moveAngleUsed.shape[1] - moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, moveAngleUsed.shape[0] - moveHeight), (moveWidth13, moveAngleUsed.shape[0]), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1] - moveWidth13, moveAngleUsed.shape[0] - moveHeight),
                         (moveAngleUsed.shape[1], moveAngleUsed.shape[0]), 0, -1)

        image_show("MoveAngle", moveAngleUsed)

        cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
        if len(cnts) == 0:
            res["result"] = "error"
            res["info"] = "{} 框 找内板失败,没有找到任何的轮廓".format(boardPos)
            res["calcSize"] = (totalWidthMm, totalHeightMm)
            res["calcError"] = (round(totalWidthMm - width / cp.mm2pix, 2), round(totalHeightMm - height / cp.mm2pix))
            return res

        cntFindAgain = False  # 是否需要再找一遍轮廓
        _, (w, h), _ = cv.minAreaRect(cntsSorted[0])
        rectBox = cv.minAreaRect(cntsSorted[0])
        rectBoxPoints = np.int0(cv.boxPoints(rectBox))
        leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
        cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
        image_show("InnerBoardFinded", useImage)
        res["box"] = [leftTop, rightTop, rightBottom, leftBottom]
        widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
        heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
        res["calcSize"] = (widthFinded, heightFinded)
        res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
        areaFinded = w * h
        if areaFinded < 0.7 * boardArea:
            res["result"] = "error"
            res["info"] = "{} 框 找内板失败,找到的内板面积过小".format(boardPos)
            return res
        elif boardArea > 1.4 * boardArea:
            res["result"] = "error"
            res["info"] = "{} 框 找内板失败,找到的内板的面积过大".format(boardPos)
        else:
            # 获取到物料边缘的距离
            line1 = [leftTop, rightTop]
            line2 = [rightTop, rightBottom]
            line3 = [rightBottom, leftBottom]
            line4 = [leftBottom, leftTop]

            line5 = [(0, 0), (totalWidthPix, 0)]
            line6 = [(totalWidthPix, 0), (totalWidthPix, totalHeightPix)]
            line7 = [(totalWidthPix, totalHeightPix), (0, totalHeightPix)]
            line8 = [(0, totalHeightPix), (0, 0)]

            offset1 = get_two_line_distance(line1, line5) / cp.mm2pix
            offset2 = get_two_line_distance(line2, line6) / cp.mm2pix
            offset3 = get_two_line_distance(line3, line7) / cp.mm2pix
            offset4 = get_two_line_distance(line4, line8) / cp.mm2pix

            print("offsetMm: {:.2f}, {:.2f}, {:.2f}, {:.2f}, offsetPix: {},{},{},{}".format(
                offset1, offset2, offset3, offset4, int(offset1 * cp.mm2pix), int(offset2 * cp.mm2pix),
                int(offset3 * cp.mm2pix), int(offset4 * cp.mm2pix)))

            if boardPos == "up":
                offset1Limit = 10
                offset3Limit = 10
            else:
                offset1Limit = 10
                offset3Limit = 10

            # 推测第一边
            if offset1 < offset1Limit and offset3 > offset3Limit:
                findLineBoard = board.copy()[:int(board.shape[0] * 0.4), :]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeTop", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        lineLength = distance((x1, y1,), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle > 45):
                            continue
                        if boardPos == "up":
                            yMin = 10 * cp.mm2pix
                            yMax = board.shape[0] - height - 10 * cp.mm2pix
                        else:
                            yMin = 10 * cp.mm2pix
                            yMax = board.shape[0] - height - 10 * cp.mm2pix
                        if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and \
                                yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)

                if len(linesList) >= 2:
                    image_show("EdgeFindedTop", board1)
                    cntFindAgain = True
                    if boardPos == "up":
                        linesListFinal = sorted(linesList, key=lambda x: x[1])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[1], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    slicePos = int(min(y1, y2))  # 按照最小的那个去截取
                    moveAngleUsed[:slicePos, :] = 0
                    image_show("moveAngleAfterSliceTop", moveAngleUsed)

            # 如果第一边位置是对的,推测第三边
            if offset1 > offset1Limit and offset3 < offset3Limit:
                yOffset = int(board.shape[0] * 0.6)
                findLineBoard = board.copy()[yOffset:, :]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeBottom", findLineBoard)

                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        y1 += yOffset
                        y2 += yOffset
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) > 45:
                            continue
                        if boardPos == "up":
                            yMin = 10 * cp.mm2pix
                            yMax = board1.shape[0] - 10 * cp.mm2pix
                        else:
                            yMin = 10 * cp.mm2pix
                            yMax = board1.shape[0] - 8 * cp.mm2pix

                        if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and \
                                yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)

                if len(linesList) >= 2:
                    image_show("EdgeFindedBottom", board1)
                    cntFindAgain = True
                    if boardPos == "up" or boardPos == "middle":
                        linesListFinal = sorted(linesList, key=lambda x: x[1])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[1], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    slicePos = int(max(y1, y2))  # 按最大的那个去截取
                    moveAngleUsed[slicePos:, :] = 0
                    image_show("moveAngleAfterSliceBottom", moveAngleUsed)

            # 如果第二边是对的,第四边是错误的,就证明第四边需要重新加载.
            if offset2 > 10 and offset4 < 10:
                findLineBoard = board.copy()[:, :int(board.shape[1] * 0.4)]
                image_show("boardUsed", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeLeft", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) < 45:
                            continue

                        xMin = 8 * cp.mm2pix
                        xMax = board1.shape[1] / 4
                        if abs(x2 - x1) < 10 * cp.mm2pix and abs(y2 - y1) > 5 * cp.mm2pix and xMin < x1 < xMax and \
                                xMin < x2 < xMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
                if len(linesList) >= 2:
                    image_show("EdgeFindedLeft", board1)
                    cntFindAgain = True
                    if chooseCloseInner:
                        linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[0])
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    x1 = targetLine[0][0]
                    x2 = targetLine[1][0]
                    slicePos = int(min(x1, x2))
                    moveAngleUsed[:, :slicePos] = 0
                    image_show("moveAngleAfterSliceLeft", moveAngleUsed)

            if offset2 < 10 and offset4 > 10:
                xOffset = int(board.shape[1] * 0.6)
                findLineBoard = board.copy()[:, xOffset:]
                image_show("boardUsed", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeLeft", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        x1 += xOffset
                        x2 += xOffset
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) < 45:
                            continue

                        xMin = board1.shape[1] / 4
                        xMax = board1.shape[1] - 8 * cp.mm2pix
                        if abs(x2 - x1) < 10 * cp.mm2pix and abs(y2 - y1) > 5 * cp.mm2pix and xMin < x1 < xMax and \
                                xMin < x2 < xMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
                if len(linesList) >= 2:
                    image_show("EdgeFindedLeft", board1)
                    cntFindAgain = True
                    if chooseCloseInner:
                        linesListFinal = sorted(linesList, key=lambda x: x[0])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    x1 = targetLine[0][0]
                    x2 = targetLine[1][0]
                    slicePos = int(max(x1, x2))
                    moveAngleUsed[:, slicePos:] = 0
                    image_show("moveAngleAfterSliceLeft", moveAngleUsed)

            if cntFindAgain:
                cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
                cnts = imutils.grab_contours(cnts)
                cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
                rectBox = cv.minAreaRect(cntsSorted[0])
                rectBoxPoints = np.int0(cv.boxPoints(rectBox))
                useImage = boardColor.copy()
                cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
                image_show("InnerBoardFindedByFillEdgeZero", useImage)
                leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
                res["box"] = leftTop, rightTop, rightBottom, leftBottom
                widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)

            topLineAngle = get_angle_by_k(get_line_k(leftTop, rightTop))
            if abs(topLineAngle) > 18:
                res["result"] = "error"
                res["info"] = "识别的内框的第一边的角度太大,角度为: {:.2f}".format(topLineAngle)
                res["calcSize"] = (widthFinded, heightFinded)
                res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                return res

            res["calcSize"] = (widthFinded, heightFinded)
            res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))

            if widthFinded < widthMin or heightFinded < heightMin:
                res["result"] = "small"
                res["info"] = "{} 框,识别的尺寸过小,识别尺寸:{}".format(boardPos, res["calcSize"])
                return res
            if widthFinded > widthMax or heightFinded > heightMax:
                res["result"] = "big"
                res["info"] = "{} 框,识别的尺寸过大,识别尺寸:{}".format(boardPos, res["calcSize"])
                return res

            # 再计算一次是否有错误的信息
            line1 = [leftTop, rightTop]
            line2 = [rightTop, rightBottom]
            line3 = [rightBottom, leftBottom]
            line4 = [leftTop, leftBottom]

            offset1 = get_two_line_distance(line1, line5) / cp.mm2pix
            offset2 = get_two_line_distance(line2, line6) / cp.mm2pix
            offset3 = get_two_line_distance(line3, line7) / cp.mm2pix
            offset4 = get_two_line_distance(line4, line8) / cp.mm2pix
            if min(offset1, offset2, offset3, offset4) < 8:
                res["info"] = "识别的内框太靠近物料边缘: {:.2f},{:.2f},{:.2f},{:.2f}".format(offset1, offset2, offset3, offset4)
                res["calcSize"] = (widthFinded, heightFinded)
                res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                return res
            boxFinded = res["box"]
            if boardPos == "middle":
                middleBoxPoints = [(p[0], p[1] + int((totalBoardHeight * middleBoxSlice[0]))) for p in boxFinded]
                isOverlap = check_two_box_is_overlap(nearBox, middleBoxPoints)
                if isOverlap:
                    res["result"] = "error"
                    res["info"] = "上框和中框出现叠板,识别失败~"
                    return res
            if boardPos == "down":
                downBoxPoints = [(p[0], p[1] + int(totalBoardHeight * downBoxSlice)) for p in boxFinded]
                isOverlap = check_two_box_is_overlap(nearBox, downBoxPoints)
                if isOverlap:
                    res["result"] = "error"
                    res["info"] = "中框和下框出现叠板,识别失败~"
                    return res
            res["result"] = "ok"
            res["info"] = "识别成功!"
            return res
    except Exception as e:
        errorInfo = "in check_inner_board_size() error: {}".format(str(e))
        print(errorInfo)
        res["result"] = "error"
        res["info"] = errorInfo
        res["calcSize"] = (totalWidthMm, totalHeightMm)
        res["calcError"] = (round(totalWidthMm - width / cp.mm2pix, 2), round(totalHeightMm - height / cp.mm2pix, 2))
        return res


def get_boxes_3(image, width, height, calcThresBig, calcThresSmall, totalBoardBox, boardThresWithAngle):
    """
    3拼板获取内板的逻辑流程
    :param image:
    :param width:
    :param height:
    :param calcThresBig:
    :param calcThresSmall:
    :param totalBoardBox:
    :param boardThresWithAngle:
    :return:
    """
    print("in get_boxes_3")
    _, (w, h), _ = totalBoardBox
    totalBoard,totalBoardOffset = get_board_widthout_angle_and_board_offset(image, totalBoardBox)
    totalBoardColor = cv.cvtColor(totalBoard, cv.COLOR_GRAY2BGR)
    jointLineMask = np.ones(image.shape, dtype=np.uint8) * 255
    jointLineMask[:, jointLinePos - jointLineExtend:jointLinePos + jointLineExtend] = 0  # 中缝拼接处的处理
    jointLineMaskRotated = get_board_widthout_angle(jointLineMask, totalBoardBox)

    jointLineMask2 = np.zeros(image.shape, dtype=np.uint8)
    jointLineMask2[:, jointLinePos - jointLineExtend:jointLinePos + jointLineExtend] = 255  # 中缝拼接处的处理
    jointLineMaskRotated2 = get_board_widthout_angle(jointLineMask2, totalBoardBox)
    totalBoardThres = get_board_widthout_angle(boardThresWithAngle, totalBoardBox)
    image_show("TotalBoard", totalBoard)
    upBoard = totalBoard.copy()[:int(h * upBoxSlice), :]
    middleBoard = totalBoard.copy()[int(h * middleBoxSlice[0]):int(h * middleBoxSlice[1]), :]
    downBoard = totalBoard.copy()[int(h * downBoxSlice):, :]
    upJointLine = jointLineMaskRotated.copy()[:int(h * upBoxSlice), :]
    middleJointLine = jointLineMaskRotated.copy()[int(h * middleBoxSlice[0]):int(h * middleBoxSlice[1]), :]
    downJointLine = jointLineMaskRotated.copy()[int(h * downBoxSlice):, :]

    upJointLine2 = jointLineMaskRotated2.copy()[:int(h * upBoxSlice), :]
    middleJointLine2 = jointLineMaskRotated2.copy()[int(h * middleBoxSlice[0]):int(h * middleBoxSlice[1]), :]
    downJointLine2 = jointLineMaskRotated2.copy()[int(h * downBoxSlice):, :]

    boxesRes = []
    upRes, upInfo, upBox = get_inner_board_info_3(upBoard, upJointLine, upJointLine2, width, height,
                                                  calcThresBig, calcThresSmall, "up",
                                                  nearBox=None, totalBoardHeight=h)
    if upRes != "ok":
        return False, upInfo, boxesRes, totalBoard, totalBoardThres,totalBoardOffset
    middleRes, middleInfo, middleBox = get_inner_board_info_3(middleBoard, middleJointLine, middleJointLine2, width, height,
                                                              calcThresBig, calcThresSmall, "middle",
                                                              nearBox=upBox, totalBoardHeight=h)
    if middleRes != "ok":
        return False, middleInfo, boxesRes, totalBoard, totalBoardThres,totalBoardOffset
    downRes, downInfo, downBox = get_inner_board_info_3(downBoard, downJointLine, downJointLine2, width, height,
                                                        calcThresBig, calcThresSmall, "down",
                                                        nearBox=middleBox, totalBoardHeight=h)
    if upRes == "ok" and downRes == "ok" and middleRes == "ok":
        middleBoxPoints = [(p[0], p[1] + int((h * middleBoxSlice[0]))) for p in middleBox]
        downBoxPoints = [(p[0], p[1] + int(h * downBoxSlice)) for p in downBox]
        middleBox = middleBoxPoints
        downBox = downBoxPoints
        cv.drawContours(totalBoardColor, [np.array(upBox), np.array(middleBox), np.array(downBox)], -1, (0, 255, 0), 2)
        image_show("ThreeBoxes", totalBoardColor)
        boxesRes = [upBox, middleBox, downBox]
        return True, "三内框查找成功", boxesRes, totalBoard, totalBoardThres,totalBoardOffset
    else:
        return False, upInfo + middleInfo + downInfo, boxesRes, totalBoard, totalBoardThres,totalBoardOffset


def get_first_check_result_three(image, width, height, totalBoardBox):
    """
    三拼板,获取第一片板的数据
    :param image:
    :param width:
    :param height:
    :param totalBoardBox:
    :return:
    """
    totalBoard = get_board_widthout_angle(image, totalBoardBox, extend=False)
    jointLineMask1 = np.ones(image.shape, dtype=np.uint8) * 255
    jointLineMask1[:, jointLinePos - jointLineExtend:jointLinePos + jointLineExtend] = 0
    jointLineMask2 = np.zeros(image.shape, dtype=np.uint8)
    jointLineMask2[:, jointLinePos - jointLineExtend:jointLinePos + jointLineExtend] = 255

    jointLineMaskRotated1 = get_board_widthout_angle(jointLineMask1, totalBoardBox, extend=False)
    jointLineMaskRotated2 = get_board_widthout_angle(jointLineMask2, totalBoardBox, extend=False)

    _, (w, h), angle = totalBoardBox
    upBoard = totalBoard.copy()[:int(h * upBoxSlice), :]
    upBoardColor = cv.cvtColor(upBoard, cv.COLOR_GRAY2BGR)
    upJointLine1 = jointLineMaskRotated1.copy()[:int(h * upBoxSlice), :]
    upJointLine2 = jointLineMaskRotated2.copy()[:int(h * upBoxSlice), :]
    upRes, upSizes, upBoxes = get_inner_board_info_for_size_check(upBoard, upJointLine1, upJointLine2, width, height)
    upBoardResList = []
    upSizeResList = []
    if upRes == "ok":
        for index, upBox in enumerate(upBoxes):
            if upBox is not None:
                upBoardRes = upBoardColor.copy()
                cv.putText(upBoardRes, "{}".format(index + 1),
                           (int(upBoardColor.shape[1] / 2 - 8), int(upBoardColor.shape[1] / 2)),
                           cv.FONT_HERSHEY_COMPLEX, 10, (255, 0, 0), 10)

                cv.drawContours(upBoardRes, [np.array(upBox)], -1, (0, 255, 0), 2)
                image_show("upBoardRes", upBoardRes)
                upBoardResList.append(upBoardRes)
                upSizeResList.append(upSizes[index])
        return "ok", upSizeResList, upBoardResList
    else:
        return "error", "内板识别出错", None


def find_total_board(image):
    """
    找到板子的整个物料区域
    :param image:图像
    :return:
    """
    # 1. 先按照阈值进行阈值分割
    thresUsed = image[50:250, 100:1000]
    thresUsedVal = np.mean(thresUsed) + 15
    filterArea = 4500
    T, board = cv.threshold(image, thresUsedVal, 255, cv.THRESH_BINARY)
    cnts = cv.findContours(board.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    cnts = sorted(cnts, key=cv.contourArea, reverse=True)

    # 2. 然后将找到的所有的满足条件的区域,通过白线连接起来,形成整个物料框
    largeContours = [cnt for cnt in cnts if cv.contourArea(cnt) > filterArea]
    if len(largeContours) >= 2:
        centerPoints = [get_center_by_contour(contour) for contour in largeContours]
        for index, center in enumerate(centerPoints):
            anotherCenter = centerPoints[(index + 1) % len(centerPoints)]
            cv.line(board, center, anotherCenter, 255, 50)
        image_show("JointCenterLine", board)

        # 连线之后再找一遍
        cnts = cv.findContours(board.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntsFirstFinded = sorted(cnts, key=cv.contourArea, reverse=True)[0]
    else:
        cntsFirstFinded = largeContours[0]

    # 3. 这个轮廓找到以后,将这个轮廓的四个角的影响去除掉,再找一次,这里的宽高,应该用整个物料的尺寸去做
    rectPoints = np.int0(cv.boxPoints(cv.minAreaRect(cntsFirstFinded)))
    leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectPoints)
    totalWidth = distance(leftTop, rightTop)
    totalHeight = distance(leftTop, leftBottom)
    boardFinal = cv.drawContours(image.copy(), [cntsFirstFinded], -1, 255, -1)
    image_show("BoardFinalUsed", boardFinal)
    moveWidth = int(totalWidth * 0.15)
    moveHeight = int(totalHeight * 0.15)
    extend = int(cp.mm2pix * 15)  # 延长10个毫米

    boardFinal[leftTop[1] - extend:leftTop[1] + moveHeight, leftTop[0] - extend:leftTop[0] + moveWidth] = 0
    boardFinal[rightTop[1] - extend:rightTop[1] + moveHeight, rightTop[0] - moveWidth:rightTop[0] + extend] = 0
    boardFinal[leftBottom[1] - moveHeight:leftBottom[1] + extend, leftBottom[0] - extend:leftBottom[0] + moveWidth] = 0
    boardFinal[rightBottom[1] - moveHeight:rightBottom[1] + extend, rightBottom[0] - moveWidth:rightBottom[0] + extend] = 0
    image_show("FinalBoardAngleMoved", boardFinal)

    # 4. 最后再找一遍轮廓
    T, board = cv.threshold(boardFinal, thresUsedVal, 255, cv.THRESH_BINARY)
    image_show("FinalBoardThres", board)

    cnts = cv.findContours(board.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    largeContours = [cnt for cnt in cnts if cv.contourArea(cnt) > filterArea]

    if len(largeContours) >= 2:
        centerPoints = [get_center_by_contour(contour) for contour in largeContours]
        for index, center in enumerate(centerPoints):
            anotherCenter = centerPoints[(index + 1) % len(centerPoints)]
            cv.line(board, center, anotherCenter, 255, 50)
        image_show("JointCenterLine", board)

        # 5. 连线之后再找一遍
        cnts = cv.findContours(board.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntFinalFinded = sorted(cnts, key=cv.contourArea, reverse=True)[0]
    else:
        cntFinalFinded = largeContours[0]

    totalBoardThres = board.copy()
    cv.drawContours(totalBoardThres, cntFinalFinded, -1, 255, -1)
    image_show("TotalBoardThres", totalBoardThres)

    box = cv.minAreaRect(cntFinalFinded)
    (cx, cy), (w, h), angle = box
    if angle > 70:
        angle = 90 - angle
        box = (cx, cy), (h, w), angle
    elif angle < -70:
        angle += 90
        box = (cx, cy), (h, w), angle

    imageColor = cv.cvtColor(image, cv.COLOR_GRAY2BGR)
    rectPoints = np.int0(cv.boxPoints(box))
    boxMask = np.zeros(image.shape, dtype=np.uint8)
    cv.drawContours(boxMask, [rectPoints], -1, 255, -1)
    cv.drawContours(imageColor, [rectPoints], -1, (0, 255, 0), 2)
    image_show("TotalBoard", imageColor)
    return image, box, totalBoardThres


def get_lines_with_three_boxes(image, totalBoard, totalBoardBox, totalBoardThres, boxList, transMtx,
                               topRemain, leftRemain, bottomRemain, rightRemain,totalBoardOffset):
    """
    根据识别出来的内框去获取切线
    :param image:
    :param totalBoard:
    :param totalBoardBox:
    :param totalBoardThres:
    :param boxList:
    :param transMtx:
    :param topRemain:
    :param leftRemain:
    :param bottomRemain:
    :param rightRemain:
    :return:
    """
    if len(image.shape) >= 3:
        image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    imageColor = cv.cvtColor(image, cv.COLOR_GRAY2BGR)

    (cx, cy), (w, h), totalBoardAngle = totalBoardBox
    upBox, middleBox, downBox = boxList
    upLeftTop, upRightTop, upRightBottom, upLeftBottom = upBox
    middleLeftTop, middleRightTop, middleRightBottom, middleLeftBottom = middleBox
    downLeftTop, downRightTop, downRightBottom, downLeftBottom = downBox

    leftCutLineK = get_linear_fit_k_vertical(np.array([upLeftTop, upLeftBottom,
                                                       middleLeftTop, middleLeftBottom,
                                                       downLeftTop, downLeftBottom]))
    if leftCutLineK is None:
        leftCutLineB = min(upLeftTop[0], upLeftBottom[0], middleLeftTop[0],
                           middleLeftBottom[0], downLeftTop[0], downLeftBottom[0]) - leftRemain
    else:
        upLeftTopX = upLeftTop[1] - (upLeftTop[0] - leftRemain) * leftCutLineK
        upLeftBottomX = upLeftBottom[1] - (upLeftBottom[0] - leftRemain) * leftCutLineK
        middleLeftTopX = middleLeftTop[1] - (middleLeftTop[0] - leftRemain) * leftCutLineK
        middleLeftBottomX = middleLeftBottom[1] - (middleLeftBottom[0] - leftRemain) * leftCutLineK
        downLeftTopX = downLeftTop[1] - (downLeftTop[0] - leftRemain) * leftCutLineK
        downLeftBottomX = downLeftBottom[1] - (downLeftBottom[0] - leftRemain) * leftCutLineK

        if leftCutLineK > 0:  # 当k大于0的时候,b越大,越靠左
            leftCutLineB = max(upLeftTopX, upLeftBottomX, middleLeftTopX, middleLeftBottomX, downLeftTopX, downLeftBottomX)
        else:
            leftCutLineB = min(upLeftTopX, upLeftBottomX, middleLeftTopX, middleLeftBottomX, downLeftTopX, downLeftBottomX)

    rightCutLineK = get_linear_fit_k_vertical(np.array([upRightTop, upRightBottom, middleRightTop,
                                                        middleRightBottom, downRightTop, downRightBottom]))
    if rightCutLineK is None:
        rightCutLineB = max(upRightTop[0], upRightBottom[0], middleRightTop[0], middleRightBottom[0],
                            downRightTop[0], downRightBottom[0]) + rightRemain
    else:
        upRightTopX = upRightTop[1] - (upRightTop[0] + rightRemain) * rightCutLineK
        upRightBottomX = upRightBottom[1] - (upRightBottom[0] + rightRemain) * rightCutLineK
        middleRightTopX = middleRightTop[1] - (middleRightTop[0] + rightRemain) * rightCutLineK
        middleRightBottomX = middleRightBottom[1] - (middleRightBottom[0] + rightRemain) * rightCutLineK
        downRightTopX = downRightTop[1] - (downRightTop[0] + rightRemain) * rightCutLineK
        downRightBottomX = downRightBottom[1] - (downRightBottom[0] + rightRemain) * rightCutLineK
        if rightCutLineK > 0:  # 当k大于0的时候,b越大,越靠左
            rightCutLineB = min(upRightTopX, upRightBottomX, middleRightTopX, middleRightBottomX,
                                downRightTopX, downRightBottomX)
        else:
            rightCutLineB = max(upRightTopX, upRightBottomX, middleRightTopX, middleRightBottomX,
                                downRightTopX, downRightBottomX)

    topCutLineK = get_line_k(upLeftTop, upRightTop)
    if topCutLineK is None:
        cv.destroyAllWindows()
        return False, None, None
    else:
        topCutLineB = topCutLineK * -1 * (upLeftTop[0]) + (upLeftTop[1] - topRemain)

    bottomCutLineK = get_line_k(downLeftBottom, downRightBottom)
    if bottomCutLineK is None:
        # 垂直，一定是异常
        cv.destroyAllWindows()
        return False, None, None, None
    else:
        bottomCutLineB = bottomCutLineK * -1 * (downLeftBottom[0]) + downLeftBottom[1] + bottomRemain

    # 先分别求出来两个中缝的角度,firstMiddleK,secondMiddleK,然后两个中缝求一个角平分线,按照这个角平分线搞中缝的角度
    firstMiddleK, firstMiddleB = get_middle_cut_line(upLeftBottom, upRightBottom, middleLeftTop, middleRightTop)
    secondMiddleK, secondMiddleB = get_middle_cut_line(middleLeftBottom, middleRightBottom, downLeftTop, downRightTop)
    # 求中点,两个中点y值,一个是上框和中框的中点的中点,一个是中框和下框的中点的y值
    firstMiddleY = (get_two_points_middle(upLeftBottom,upRightBottom)[1] +
                    get_two_points_middle(middleLeftTop,middleRightTop)[1]) / 2
    secondMiddleY = (get_two_points_middle(middleLeftBottom,middleRightBottom)[1] +
                     get_two_points_middle(downLeftTop,downRightTop)[1]) / 2
    firstMiddleLine, secondMiddleLine = get_two_lines_angular_bisector(firstMiddleK, firstMiddleB, secondMiddleK,
                                                                       secondMiddleB,firstMiddleY,secondMiddleY)
    firstMiddleK, firstMiddleB = firstMiddleLine
    secondMiddleK, secondMiddleB = secondMiddleLine

    boardLeftTop = [0, 0]
    boardRightTop = [w, 0]
    boardLeftBottom = [0, h]
    boardRightBottom = [w, h]

    if topRemain == 0:
        topLineK, topLineB = find_first_edge_line(totalBoard, totalBoardThres)
        if topLineK is not None:
            topCutLineK, topCutLineB = topLineK, topLineB
        else:
            topCutLineK, topCutLineB = get_line_k_and_b(boardLeftTop, boardRightTop)

    if bottomRemain == 0:
        bottomLineK, bottomLineB = find_third_edge_line(totalBoard, totalBoardThres)
        if bottomLineK is not None:
            bottomCutLineK, bottomCutLineB = bottomLineK, bottomLineB
        else:
            bottomCutLineK, bottomCutLineB = get_line_k_and_b(boardLeftBottom, boardRightBottom)
    if leftRemain == 0:
        leftCutLineK, leftCutLineB = get_line_k_and_b(boardLeftBottom, boardLeftTop)
    if rightRemain == 0:
        rightCutLineK, rightCutLineB = get_line_k_and_b(boardRightTop, boardRightBottom)

    # 求所有线的交点
    leftTopCross = get_two_lines_intersection(topCutLineK, topCutLineB, leftCutLineK, leftCutLineB)
    rightTopCross = get_two_lines_intersection(topCutLineK, topCutLineB, rightCutLineK, rightCutLineB)
    leftFirstMiddleCross = get_two_lines_intersection(firstMiddleK, firstMiddleB, leftCutLineK, leftCutLineB)
    rightFirstMiddleCross = get_two_lines_intersection(firstMiddleK, firstMiddleB, rightCutLineK, rightCutLineB)
    leftSecondMiddleCross = get_two_lines_intersection(secondMiddleK, secondMiddleB, leftCutLineK, leftCutLineB)
    rightSecondMiddleCross = get_two_lines_intersection(secondMiddleK, secondMiddleB, rightCutLineK, rightCutLineB)
    leftBottomCross = get_two_lines_intersection(bottomCutLineK, bottomCutLineB, leftCutLineK, leftCutLineB)
    rightBottomCross = get_two_lines_intersection(bottomCutLineK, bottomCutLineB, rightCutLineK, rightCutLineB)

    extend = int(8 * cp.mm2pix)
    extendLeftRight = int(15 * cp.mm2pix)

    topCutLeftPoint = [- extend, topCutLineK * (- extend) + topCutLineB]
    topCutRightPoint = [extend + w, topCutLineK * (extend + w) + topCutLineB]

    bottomCutRightPoint = [w + extend, bottomCutLineK * (w + extend) + bottomCutLineB]
    bottomCutLeftPoint = [- extend, bottomCutLineK * (- extend) + bottomCutLineB]

    if leftCutLineK is None:
        # 按照整个物料的高度去延长切线
        # leftCutLineBottom = [leftCutLineB, h + extendLeftRight]
        # leftCutLineTop = [leftCutLineB, -extendLeftRight]
        # 按照交点延长去切
        leftCutLineBottom = [leftCutLineB, leftBottomCross[1] + extendLeftRight]
        leftCutLineTop = [leftCutLineB, leftTopCross[1] - extendLeftRight]
    elif leftCutLineK != 0:
        # 按照整个物料的高度去延长切线
        # leftCutLineBottom = [((h + extendLeftRight) - leftCutLineB) / leftCutLineK, h + extendLeftRight]
        # leftCutLineTop = [(- extendLeftRight - leftCutLineB) / leftCutLineK, - extendLeftRight]
        # 按照和1,3刀的交点延长切线
        leftCutLineBottom = [((leftBottomCross[1] + extendLeftRight) - leftCutLineB) / leftCutLineK,
                             leftBottomCross[1] + extendLeftRight]
        leftCutLineTop = [(leftTopCross[1] - extendLeftRight - leftCutLineB) / leftCutLineK,
                          leftTopCross[1] - extendLeftRight]
    else:
        cv.destroyAllWindows()
        return False, None, None, None

    if rightCutLineK is None:
        # 按照整个物料的高度去延长切线
        # rightCutLineTop = [rightCutLineB, - extendLeftRight]
        # rightCutLineBottom = [rightCutLineB, h + extendLeftRight]
        # 按照和13刀的交点去延长切线
        rightCutLineTop = [rightCutLineB, rightTopCross[1] - extendLeftRight]
        rightCutLineBottom = [rightCutLineB, rightBottomCross[1] + extendLeftRight]
    elif rightCutLineK != 0:
        # 按照整个物料的高度去延长切线
        # rightCutLineTop = [((- extendLeftRight) - rightCutLineB) / rightCutLineK,
        #                    - extendLeftRight]
        # rightCutLineBottom = [((h + extendLeftRight) - rightCutLineB) / rightCutLineK,
        #                       h + extendLeftRight]
        # 按照和13刀的交点去延长切线
        rightCutLineTop = [((rightTopCross[1] - extendLeftRight) - rightCutLineB) / rightCutLineK,
                           rightTopCross[1] - extendLeftRight]
        rightCutLineBottom = [((rightBottomCross[1] + extendLeftRight) - rightCutLineB) / rightCutLineK,
                              rightBottomCross[1] + extendLeftRight]
    else:
        cv.destroyAllWindows()
        return False, None, None, None
    rotatedCenter = (cx,cy)
    M = cv.getRotationMatrix2D(rotatedCenter, -totalBoardAngle, 1)
    centerOffset = totalBoardOffset

    boardLeftTopBig = np.dot (M, [boardLeftTop[0] + centerOffset[0], boardLeftTop[1] + centerOffset[1], 1])
    boardRightTopBig = np.dot(M, [boardRightTop[0] + centerOffset[0], boardRightTop[1] + centerOffset[1], 1])
    boardRightBottomBig = np.dot(M, [boardRightBottom[0] + centerOffset[0], boardRightBottom[1] + centerOffset[1], 1])
    boardLeftBottomBig = np.dot(M, [boardLeftBottom[0] + centerOffset[0], boardLeftBottom[1] + centerOffset[1], 1])

    topCutLeftPointBig = np.dot(M, [topCutLeftPoint[0] + centerOffset[0], topCutLeftPoint[1] + centerOffset[1], 1])
    topCutRightPointBig = np.dot(M, [topCutRightPoint[0] + centerOffset[0], topCutRightPoint[1] + centerOffset[1], 1])
    bottomCutRightPointBig = np.dot(M, [bottomCutRightPoint[0] +  centerOffset[0], bottomCutRightPoint[1] + centerOffset[1], 1])
    bottomCutLeftPointBig = np.dot(M, [bottomCutLeftPoint[0] + centerOffset[0], bottomCutLeftPoint[1] + centerOffset[1], 1])
    leftCutLineBottomBig = np.dot(M, [leftCutLineBottom[0] + centerOffset[0], leftCutLineBottom[1] + centerOffset[1], 1])
    leftCutLineTopBig = np.dot(M, [leftCutLineTop[0] + centerOffset[0], leftCutLineTop[1] + centerOffset[1], 1])
    rightCutLineTopBig = np.dot(M, [rightCutLineTop[0] + centerOffset[0], rightCutLineTop[1] + centerOffset[1], 1])
    rightCutLineBottomBig = np.dot(M, [rightCutLineBottom[0] + centerOffset[0], rightCutLineBottom[1] + centerOffset[1], 1])


    firstMiddleCutLineLeftBig = np.dot(M, [leftFirstMiddleCross[0] + centerOffset[0],
                                           leftFirstMiddleCross[1] + centerOffset[1],1])
    firstMiddleCutLineRightBig = np.dot(M, [rightFirstMiddleCross[0] + centerOffset[0],
                                            rightFirstMiddleCross[1] + centerOffset[1],1])
    secondMiddleCutLineLeftBig = np.dot(M, [leftSecondMiddleCross[0] + centerOffset[0],
                                            leftSecondMiddleCross[1] + centerOffset[1],1])
    secondMiddleCutLineRightBig = np.dot(M, [rightSecondMiddleCross[0] + centerOffset[0],
                                             rightSecondMiddleCross[1] + centerOffset[1],1])

    # 重新将端点定位到大图上去
    upLeftBottom = np.dot(M, [upLeftBottom[0] + centerOffset[0], upLeftBottom[1] + centerOffset[1], 1])
    upRightBottom = np.dot(M, [upRightBottom[0] + centerOffset[0], upRightBottom[1] + centerOffset[1], 1])
    upLeftTop = np.dot(M, [upLeftTop[0] + centerOffset[0], upLeftTop[1] + centerOffset[1], 1])
    upRightTop = np.dot(M, [upRightTop[0] + centerOffset[0], upRightTop[1] + centerOffset[1], 1])

    middleLeftBottom = np.dot(M, [middleLeftBottom[0] + centerOffset[0], middleLeftBottom[1] + centerOffset[1], 1])
    middleRightBottom = np.dot(M, [middleRightBottom[0] + centerOffset[0], middleRightBottom[1] + centerOffset[1], 1])
    middleLeftTop = np.dot(M, [middleLeftTop[0] + centerOffset[0], middleLeftTop[1] + centerOffset[1], 1])
    middleRightTop = np.dot(M, [middleRightTop[0] + centerOffset[0], middleRightTop[1] + centerOffset[1], 1])

    downLeftTop = np.dot(M, [downLeftTop[0] + centerOffset[0], downLeftTop[1] + centerOffset[1], 1])
    downLeftBottom = np.dot(M, [downLeftBottom[0] + centerOffset[0], downLeftBottom[1] + centerOffset[1], 1])
    downRightTop = np.dot(M, [downRightTop[0] + centerOffset[0], downRightTop[1] +centerOffset[1], 1])
    downRightBottom = np.dot(M, [downRightBottom[0] + centerOffset[0], downRightBottom[1] + centerOffset[1], 1])

    # 画出内框
    cv.line(imageColor, (int(upLeftBottom[0]), int(upLeftBottom[1])), (int(upRightBottom[0]), int(upRightBottom[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(upLeftBottom[0]), int(upLeftBottom[1])), (int(upLeftTop[0]), int(upLeftTop[1])), colorGreen,
            3)
    cv.line(imageColor, (int(upRightBottom[0]), int(upRightBottom[1])), (int(upRightTop[0]), int(upRightTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(upLeftTop[0]), int(upLeftTop[1])), (int(upRightTop[0]), int(upRightTop[1])), colorGreen, 3)

    cv.line(imageColor, (int(downLeftBottom[0]), int(downLeftBottom[1])),
            (int(downRightBottom[0]), int(downRightBottom[1])), colorGreen, 3)
    cv.line(imageColor, (int(downLeftBottom[0]), int(downLeftBottom[1])), (int(downLeftTop[0]), int(downLeftTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(downRightBottom[0]), int(downRightBottom[1])), (int(downRightTop[0]), int(downRightTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(downLeftTop[0]), int(downLeftTop[1])), (int(downRightTop[0]), int(downRightTop[1])),
            colorGreen, 3)

    cv.line(imageColor, (int(middleLeftBottom[0]), int(middleLeftBottom[1])),
            (int(middleRightBottom[0]), int(middleRightBottom[1])), colorGreen, 3)
    cv.line(imageColor, (int(middleLeftBottom[0]), int(middleLeftBottom[1])), (int(middleLeftTop[0]), int(middleLeftTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(middleRightBottom[0]), int(middleRightBottom[1])), (int(middleRightTop[0]), int(middleRightTop[1])),
            colorGreen, 3)
    cv.line(imageColor, (int(middleLeftTop[0]), int(middleLeftTop[1])), (int(middleRightTop[0]), int(middleRightTop[1])),
            colorGreen, 3)

    # 画出上，下，左，右，中五条切线
    textScale = 3
    textThickness = 8
    cv.line(imageColor, (int(topCutLeftPointBig[0]), int(topCutLeftPointBig[1])),
            (int(topCutRightPointBig[0]), int(topCutRightPointBig[1])), colorRed , 3)
    cv.putText(imageColor, '1', (int((topCutLeftPointBig[0] + topCutRightPointBig[0]) / 2),
                                 int((topCutLeftPointBig[1] + topCutRightPointBig[1]) / 2) - 40 ),
               cv.FONT_HERSHEY_COMPLEX,textScale, colorRed,textThickness)
    cv.line(imageColor, (int(bottomCutRightPointBig[0]), int(bottomCutRightPointBig[1])),
            (int(bottomCutLeftPointBig[0]), int(bottomCutLeftPointBig[1])), colorRed, 3)
    cv.putText(imageColor, '3', (int((bottomCutRightPointBig[0] + bottomCutLeftPointBig[0]) / 2),
                                 int((bottomCutRightPointBig[1] + bottomCutLeftPointBig[1]) / 2) + 90 ),
               cv.FONT_HERSHEY_COMPLEX,textScale, colorRed, textThickness)

    cv.line(imageColor, (int(leftCutLineBottomBig[0]), int(leftCutLineBottomBig[1])),
            (int(leftCutLineTopBig[0]), int(leftCutLineTopBig[1])), colorRed, 3)
    cv.putText(imageColor, '2', (int((leftCutLineBottomBig[0] + leftCutLineTopBig[0]) / 2) - 100  ,
                                 int((leftCutLineBottomBig[1] + leftCutLineTopBig[1]) / 2)),
               cv.FONT_HERSHEY_COMPLEX,textScale, colorRed, textThickness)
    cv.line(imageColor, (int(rightCutLineTopBig[0]), int(rightCutLineTopBig[1])),
            (int(rightCutLineBottomBig[0]), int(rightCutLineBottomBig[1])), colorRed, 3)
    cv.putText(imageColor, '4', (int((rightCutLineTopBig[0] + rightCutLineBottomBig[0]) / 2) + 30,
                                 int((rightCutLineTopBig[1] + rightCutLineBottomBig[1]) / 2)),
               cv.FONT_HERSHEY_COMPLEX,textScale, colorRed, textThickness)
    cv.line(imageColor, (int(firstMiddleCutLineLeftBig[0]), int(firstMiddleCutLineLeftBig[1])),
            (int(firstMiddleCutLineRightBig[0]), int(firstMiddleCutLineRightBig[1])), colorBlue, 3)
    cv.line(imageColor, (int(secondMiddleCutLineLeftBig[0]), int(secondMiddleCutLineLeftBig[1])),
            (int(secondMiddleCutLineRightBig[0]), int(secondMiddleCutLineRightBig[1])), colorBlue, 3)

    # 将所有的点都转换为机械手上的坐标
    topCutLeftPointRobot = pix_pos_to_robot(topCutLeftPointBig, transMtx)
    topCutRightPointRobot = pix_pos_to_robot(topCutRightPointBig, transMtx)
    bottomCutLeftPointRobot = pix_pos_to_robot(bottomCutLeftPointBig, transMtx)
    bottomCutRightPointRobot = pix_pos_to_robot(bottomCutRightPointBig, transMtx)
    leftCutLineBottomRobot = pix_pos_to_robot(leftCutLineBottomBig, transMtx)
    leftCutLineTopRobot = pix_pos_to_robot(leftCutLineTopBig, transMtx)
    rightCutLineTopRobot = pix_pos_to_robot(rightCutLineTopBig, transMtx)
    rightCutLineBottomRobot = pix_pos_to_robot(rightCutLineBottomBig, transMtx)
    firstMiddleCutLineLeftRobot = pix_pos_to_robot(firstMiddleCutLineLeftBig, transMtx)
    firstMiddleCutLineRightRobot = pix_pos_to_robot(firstMiddleCutLineRightBig, transMtx)
    secondMiddleCutLineLeftRobot = pix_pos_to_robot(secondMiddleCutLineLeftBig, transMtx)
    secondMiddleCutLineRightRobot = pix_pos_to_robot(secondMiddleCutLineRightBig, transMtx)

    boardLeftTopRobot = pix_pos_to_robot(boardLeftTopBig, transMtx)
    boardRightTopRobot = pix_pos_to_robot(boardRightTopBig, transMtx)
    boardRightBottomRobot = pix_pos_to_robot(boardRightBottomBig, transMtx)
    boardLeftBottomRobot = pix_pos_to_robot(boardLeftBottomBig, transMtx)

    cutDisTotal = 0
    cutAreaTotal = 0
    if topRemain != 0:
        cutDis = distance(topCutLeftPointRobot, topCutRightPointRobot)
        area = cutDis * (distance(get_two_points_middle(topCutLeftPointRobot, topCutRightPointRobot),
                                  get_two_points_middle(boardLeftTopRobot, boardRightTopRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis
    if leftRemain != 0:
        cutDis = distance(leftCutLineBottomRobot, leftCutLineTopRobot)
        area = cutDis * (distance(get_two_points_middle(leftCutLineBottomRobot, leftCutLineTopRobot),
                                  get_two_points_middle(boardLeftTopRobot, boardLeftBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    if bottomRemain != 0:
        cutDis = distance(bottomCutRightPointRobot, bottomCutLeftPointRobot)
        area = cutDis * (distance(get_two_points_middle(bottomCutRightPointRobot, bottomCutLeftPointRobot),
                                  get_two_points_middle(boardLeftBottomRobot, boardRightBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    if rightRemain != 0:
        cutDis = distance(rightCutLineTopRobot, rightCutLineBottomRobot)
        area = cutDis * (distance(get_two_points_middle(rightCutLineTopRobot, rightCutLineBottomRobot),
                                  get_two_points_middle(boardRightTopRobot, boardRightBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    imageResult = get_board_widthout_angle(imageColor, totalBoardBox, extend=True)
    # imageResult = cv.resize(imageResult.copy(),(int(imageResult.shape[1] / 2),int(imageResult.shape[0] / 2)),cv.INTER_AREA)
    image_show("resultImage", imageResult)
    # 以裁切机的实际切线为标准，计算前板长，后板长，总长
    # 先算中线中点
    firstLength, secondLength, thirdLength = get_board_length_three([topCutLeftPointRobot, topCutRightPointRobot],
                                                             [firstMiddleCutLineLeftRobot,firstMiddleCutLineRightRobot],
                                                              [secondMiddleCutLineLeftRobot,secondMiddleCutLineRightRobot],
                                                              [bottomCutLeftPointRobot, bottomCutRightPointRobot])

    topFirstMiddleAngle = get_two_line_angle(firstMiddleCutLineRightRobot,firstMiddleCutLineLeftRobot,
                                             topCutRightPointRobot,topCutLeftPointRobot)
    bottomFirstMiddleAngle = get_two_line_angle(firstMiddleCutLineRightRobot, firstMiddleCutLineLeftRobot,
                                                bottomCutRightPointRobot, bottomCutLeftPointRobot)
    twoMiddleAngle = get_two_line_angle(secondMiddleCutLineRightRobot,secondMiddleCutLineLeftRobot,
                                        firstMiddleCutLineRightRobot,firstMiddleCutLineLeftRobot)
    bottomSecondMiddleAngle = get_two_line_angle(secondMiddleCutLineRightRobot,secondMiddleCutLineLeftRobot,
                                                 bottomCutRightPointRobot,bottomCutLeftPointRobot)

    # 是否切第一刀
    isFirstCut = True if topRemain != 0 else False
    isThirdCut = True if bottomRemain != 0 else False
    cutLength = [round(cutDisTotal,5),round(cutAreaTotal,5)]
    cutWidth = distance(topCutLeftPointRobot, topCutRightPointRobot)
    angleList =  [topFirstMiddleAngle,bottomFirstMiddleAngle,twoMiddleAngle,bottomSecondMiddleAngle]
    print("length:{},{},{},angleList:{},{},{},{}".format(firstLength,secondLength,thirdLength,
                                                         angleList[0],angleList[1],angleList[2],angleList[3]))

    return [topCutLeftPointRobot, topCutRightPointRobot, bottomCutRightPointRobot, bottomCutLeftPointRobot,
            leftCutLineBottomRobot, leftCutLineTopRobot, rightCutLineTopRobot, rightCutLineBottomRobot,
            firstMiddleCutLineLeftRobot,firstMiddleCutLineRightRobot,secondMiddleCutLineLeftRobot,secondMiddleCutLineRightRobot,
            firstLength, secondLength, thirdLength,angleList], imageResult, cutLength, isFirstCut, isThirdCut,cutWidth



def find_first_edge_line(totalBoard, totalBoardThres):
    try:
        totalBoardColor = cv.cvtColor(totalBoard, cv.COLOR_GRAY2BGR)
        image_show("TotalBoardThres", totalBoardThres)
        board = totalBoardThres.copy()[:int(totalBoardThres.shape[0] / 4),:]
        scharrX = cv.Scharr(board, cv.CV_64F, 1, 0)
        scharrY = cv.Scharr(board, cv.CV_64F, 0, 1)
        scharrX = cv.convertScaleAbs(scharrX)
        scharrY = cv.convertScaleAbs(scharrY)
        scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.2, 0)
        board = scharrXY.copy()
        image_show("ScharrXYEdge ", board)
        minLineLengthEdge = int(20 * cp.mm2pix)
        maxLineGap = 5
        yMax = 40 * cp.mm2pix
        lines = cv.HoughLinesP(board, 1, np.pi / 180, 100, minLineLengthEdge, maxLineGap)
        board1 = totalBoardColor.copy()
        linesList = []
        for line in lines:
            for x1, y1, x2, y2 in line:
                lineLength = distance((x1, y1), (x2, y2))
                if abs(y2 - y1) < 20 * cp.mm2pix and (
                        x2 - x1) > 10 * cp.mm2pix and y1 < yMax and y2 < yMax and lineLength > minLineLengthEdge:
                    linesList.append([x1, y1, (y1 + y2) / 2])
                    linesList.append([x2, y2, (y1 + y2) / 2])
                    cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
        image_show("EdgeFinded", board1)

        # 先按照Y进行排序
        linesSortedY = sorted(linesList, key=lambda x: x[2])
        if len(linesSortedY) >= 4:
            # 获取x的方向,正负问题
            xDirection = True if (linesSortedY[-1][0] - linesSortedY[0][0]) > 0 else False  # 正向
            removeSomeWrongPointFlag = True
            while removeSomeWrongPointFlag:
                for i in range(len(linesSortedY) - 1):
                    xDif = linesSortedY[i + 1][0] - linesSortedY[i][0]
                    if xDirection and xDif <= 0:
                        linesSortedY.remove(linesSortedY[i+1])
                        break

                    if not xDirection and xDif >= 0:
                        linesSortedY.remove(linesSortedY[i+1])
                        break
                else: # 退出循环
                    removeSomeWrongPointFlag = False
        if len(linesList) >= 10:
            lineUseStart = 2
            linesRate = 0.65
            linePointsUsedCount = int(len(linesList) * linesRate)  # 选取最小的六条线进行拟合
            linesListFinal = sorted(linesList, key=lambda x: x[2])[lineUseStart:lineUseStart + linePointsUsedCount]
            print("linesFinalFinded 个数: {} :{}".format(len(linesListFinal),linesListFinal))
            linesListFinal = [line[:2] for line in linesListFinal]
            topCutLineK, topCutLineB = get_linear_fit_k_and_b_horizontal(np.array(linesListFinal))
            topCutAngle = np.arctan(topCutLineK) * 180 / np.pi
            print(topCutAngle)
            return topCutLineK, topCutLineB
        # 取中间的三个点进行拟合
        elif len(linesList) >= 4:
            lineUseStart = 1
            linesRate = 0.8
            linePointsUsedCount = int(len(linesList) * linesRate)  # 选取两个点进行拟合
            linePointsUsedCount = max([linePointsUsedCount,4]) # 就是要保证有2个数以上
            linesListFinal = sorted(linesList, key=lambda x: x[2])[lineUseStart:lineUseStart + linePointsUsedCount]
            print("linesFinalFinded 个数: {} :{}".format(len(linesListFinal),linesListFinal))
            linesListFinal = [line[:2] for line in linesListFinal]
            topCutLineK, topCutLineB = get_linear_fit_k_and_b_horizontal(np.array(linesListFinal))
            topCutAngle = np.arctan(topCutLineK) * 180 / np.pi
            print(topCutAngle)
            return topCutLineK, topCutLineB
        else:
            return None, None
    except Exception as e:
        print(str(e))
        return None, None


def find_third_edge_line(totalBoard, totalBoardThres):
    try:
        totalBoardColor = cv.cvtColor(totalBoard, cv.COLOR_GRAY2BGR)
        image_show("TotalBoardThres", totalBoardThres)
        sliceHeight = int(0.8 * totalBoard.shape[0])
        board = totalBoardThres.copy()[sliceHeight:, :]
        scharrX = cv.Scharr(board, cv.CV_64F, 1, 0)
        scharrY = cv.Scharr(board, cv.CV_64F, 0, 1)
        scharrX = cv.convertScaleAbs(scharrX)
        scharrY = cv.convertScaleAbs(scharrY)
        scharrXY = cv.addWeighted(scharrX, 0.5, scharrY, 0.5, 0)
        board = scharrXY.copy()
        image_show("SharrXYThirdEdge", board)
        minLineLengthEdge = int(20 * cp.mm2pix)
        maxLineGap = 5
        yMin = board.shape[0] - int(60 * cp.mm2pix)
        lines = cv.HoughLinesP(board, 1, np.pi / 180, 100, minLineLengthEdge, maxLineGap)
        board1 = totalBoardColor.copy()
        linesList = []
        for line in lines:
            for x1, y1, x2, y2 in line:
                lineLength = distance((x1, y1), (x2, y2))
                if abs(y2 - y1) < 20 * cp.mm2pix and (x2 - x1) > 10 * cp.mm2pix and y1 > yMin and \
                        y2 > yMin and lineLength > minLineLengthEdge:
                    y1 += sliceHeight
                    y2 += sliceHeight
                    linesList.append([x1, y1, (y1 + y2) / 2])
                    linesList.append([x2, y2, (y1 + y2) / 2])
                    cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
        # 先按照Y进行排序
        linesSortedY = sorted(linesList, key=lambda x: x[2], reverse=True)
        if len(linesSortedY) >= 4:
            # 获取x的方向,正负问题
            xDirection = True if (linesSortedY[-1][0] - linesSortedY[0][0]) > 0 else False  # 正向
            removeSomeWrongPointFlag = True
            while removeSomeWrongPointFlag:
                for i in range(len(linesSortedY) - 1):
                    xDif = linesSortedY[i + 1][0] - linesSortedY[i][0]
                    if xDirection and xDif <= 0:
                        linesSortedY.remove(linesSortedY[i+1])
                        break

                    if not xDirection and xDif >= 0:
                        linesSortedY.remove(linesSortedY[i+1])
                        break
                else: # 退出循环
                    removeSomeWrongPointFlag = False
        linesList = linesSortedY.copy()
        image_show("thirdEdgeFinded", board1)
        print("linesFinalFinded:{}个,{}".format(len(linesList), linesList))
        if len(linesList) >= 10:
            lineUseStart = 2
            linesRate = 0.65
            linePointsUsedCount = int(len(linesList) * linesRate)  # 选取两个点进行拟合
            linesListFinal = linesList[lineUseStart:lineUseStart + linePointsUsedCount]
            print("linesFinalFinded     :{}".format(linesListFinal))
            linesListFinal = [line[:2] for line in linesListFinal]
            bottomCutLineK, bottomCutLineB = get_linear_fit_k_and_b_horizontal(np.array(linesListFinal))
            bottomCutAngle = np.arctan(bottomCutLineK) * 180 / np.pi
            print("bottomCutAngle: {}".format(bottomCutAngle))
            return bottomCutLineK, bottomCutLineB
        elif len(linesList) >= 4:
            lineUseStart = 1
            linesRate = 0.8
            linePointsUsedCount = int(len(linesList) * linesRate)  # 选取两个点进行拟合
            linePointsUsedCount = max([linePointsUsedCount,4]) # 就是要保证有2个数以上
            linesListFinal = sorted(linesList, key=lambda x: x[2])[lineUseStart:lineUseStart + linePointsUsedCount]
            print("linesFinalFinded     :{}".format(linesListFinal))
            linesListFinal = [line[:2] for line in linesListFinal]
            bottomCutLineK, bottomCutLineB = get_linear_fit_k_and_b_horizontal(np.array(linesListFinal))
            bottomCutAngle = np.arctan(bottomCutLineK) * 180 / np.pi
            print("bottomCutAngle: {}".format(bottomCutAngle))
            return bottomCutLineK, bottomCutLineB
        else:
            return None, None
    except Exception as e:
        errorInfo = "in get_board_third_cut_edge(): {}".format(str(e))
        print(errorInfo)
        return None, None





if __name__ == '__main__':
    filePath = r"E:\raw_joint"
    mtx = [
        [0, 1, 0],
        [1, 0, 0]
    ]
    calcThresBig = 20
    calcThresSmall = 9
    remainEdge = [0, 11, 0, 11]
    fanzhuan = "否"
    topRemain, leftRemain, bottomRemain, rightRemain = [int(x * cp.mm2pix) for x in remainEdge]

    keepDir = filePath
    if not os.path.isdir(keepDir):
        keepDir, _ = os.path.split(filePath)

    keepOkPath = os.path.join(keepDir, "ok")
    keepOkResPath = os.path.join(keepDir, "cutlines")
    keepFailPath = os.path.join(keepDir, "fail")

    if not os.path.exists(keepOkPath):
        os.mkdir(keepOkPath)
    if not os.path.exists(keepOkResPath):
        os.mkdir(keepOkResPath)
    if not os.path.exists(keepFailPath):
        os.mkdir(keepFailPath)

    fileNames = []  # 保存要去识别的所有的图片
    if os.path.isfile(filePath):
        filePath, fileName = os.path.split(filePath)
        fileNames.append(fileName)
    else:
        for root, dirs, files in os.walk(filePath):
            if root != filePath:
                continue
            for file in files:
                if file[-4:] != ".bmp":
                    continue
                fileNames.append(file)

    for index, fileName in enumerate(fileNames):
        filePathReal = os.path.join(filePath, fileName)
        srcW, srcH = get_width_height(fileName)
        if srcW is None or srcH is None:
            print("*" * 10 + "第 {} 张图 ({}),图像名称错误,已经跳过".format(index + 1, fileName) + "*" * 10)
            continue
        print("*" * 10 + " 第 {} 张图 ({})".format(index + 1, fileName) + "*" * 10)
        imgSrc = cv.imread(filePathReal, cv.IMREAD_GRAYSCALE)
        # 算法开始调用的测试时间
        calcStart = time.time()
        res, info, imageGray, totalBoardBox, totalBoardThresWithAngle = check_total_board_is_ok_for_three(imgSrc)
        print("三拼板,物料检测: {}".format(info))
        firstCheck = False
        if firstCheck:
            res, sizeList, resList, upBoard = get_first_check_result_three(imgSrc, srcW, srcH, totalBoardBox)
            if res:
                pass

        res, info2, boxesList, totalBoard, totalBoardThres,totalBoardOffset = get_boxes_3(imgSrc, srcW, srcH, calcThresBig, calcThresSmall,
                                                                         totalBoardBox, totalBoardThresWithAngle)
        if res:
            cutLines, imgRes, cutDis, isFirstCut, isThirdCut = get_lines_with_three_boxes(imgSrc, totalBoard, totalBoardBox,
                                                                                          totalBoardThres, boxesList, mtx,
                                                                                          topRemain, leftRemain, bottomRemain,
                                                                                          rightRemain,totalBoardOffset)
            print("算法耗时: {}".format(time.time() - calcStart))

            cv.imwrite(os.path.join(keepOkPath, fileName), imgSrc)
            os.remove(filePathReal)
            cv.imwrite(os.path.join(keepOkResPath, fileName), imgRes)
            print("识别成功")
            continue
        else:
            print("算法耗时: {}".format(time.time() - calcStart))
            cv.imwrite(os.path.join(keepFailPath, fileName), imgSrc)
            os.remove(filePathReal)
            print("XXXXXXXXXXXX  识别失败  XXXXXXXXXX")
            continue

